import json
import time
import re
import os
import fitz
from openai import OpenAI
import datetime

# ========================== 1. 配置区 ==========================
API_KEY = "BearerCubJNNWPCQjooxiEbLGB:IgSlCSEPDRuFXHJlXlMw" 
URL = "https://spark-api-open.xf-yun.com/v2/chat/completions"
INPUT_DOCUMENT_PATH = r"C:/Users/cassi/Desktop/bisai/word-master/豫洛阳-兰郑长干线-CPY-0790-BFGDGS-ZZSYQFGS.docx"
OUTPUT_JSON_PATH = r"C:/Users/cassi/Desktop/bisai/word-master/standard_compliance.json"

# 仅处理第一个语义块以快速预览效果（参考 template_compliance_check.py）
PROCESS_FIRST_CHUNK_ONLY = False

 

# ========================== 2. 功能函数区 ==========================
def get_answer(message):
    try:
        client = OpenAI(
            api_key="sk-ma0HIkN3beK0mtThtDzIfRLN5IzpL4agmB9RSbpHk53h7BF5",
            base_url="https://www.chataiapi.com/v1",
        )
        response = client.chat.completions.create(
            model="gemini-2.5-pro",
            messages=message,
            temperature=0.7,
        )
        content = response.choices[0].message.content or ""
        if content.strip():
            print("\n\n*******************模型生成内容如下********************\n")
            print(content)
        return content
    except Exception as e:
        print(f"API请求失败：{str(e)}")
        return ""

def read_document(file_path):
    """读取Word (.docx, .doc) 或 PDF (.pdf) 文档，返回纯文本内容"""
    full_text = []
    file_path_lower = file_path.lower()
    try:
        if file_path_lower.endswith('.docx'):
            from docx import Document
            doc = Document(file_path)
            for para in doc.paragraphs:
                full_text.append(para.text)
            return "\n".join(full_text)
            
        elif file_path_lower.endswith('.doc'):
            try:
                import subprocess
                output_dir = os.path.dirname(file_path)
                subprocess.run(
                    ['libreoffice', '--headless', '--convert-to', 'txt:Text', '--outdir', output_dir, file_path],
                    check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=120
                )
                base_name = os.path.splitext(os.path.basename(file_path))[0]
                txt_file_path = os.path.join(output_dir, f"{base_name}.txt")
                if os.path.exists(txt_file_path):
                    with open(txt_file_path, 'r', encoding='utf-8') as f:
                        content = f.read()
                    os.remove(txt_file_path)
                    return content
                else:
                    return f"错误: LibreOffice 转换后未找到文本文件 {txt_file_path}"
            except FileNotFoundError:
                return "错误: 'libreoffice' 命令未找到。请先安装 (sudo apt-get install libreoffice-writer)。"
            except subprocess.TimeoutExpired:
                return f"错误: 使用 LibreOffice 转换文件超时 ({file_path})。"
            except subprocess.CalledProcessError as e:
                error_message = e.stderr.decode('utf-8', errors='ignore')
                return f"错误: 使用 LibreOffice 读取 .doc 文件失败。\n详细错误: {error_message}"
                
        elif file_path_lower.endswith('.pdf'):
            doc = fitz.open(file_path)
            for page_num in range(len(doc)):
                page = doc[page_num]
                full_text.append(page.get_text())
            doc.close()
            return "\n".join(full_text)
        else:
            return f"错误: 不支持的文件格式 {file_path}"
    except Exception as e:
        return f"错误: 读取文件失败 {file_path} - {str(e)}"

def semantic_chunker(text, max_chars=250, overlap=50):
    """将长文本进行自然的语义切块"""
    text = re.sub(r'\n\s*\n', '\n', text)
    paragraphs = text.split('\n')
    chunks = []
    current_chunk = ""
    
    for p in paragraphs:
        p = p.strip()
        if not p:
            continue
        if len(current_chunk) + len(p) + 1 <= max_chars:
            current_chunk += p + "\n"
        else:
            if current_chunk:
                chunks.append(current_chunk.strip())
            current_chunk = p + "\n"
    if current_chunk:
        chunks.append(current_chunk.strip())
    return chunks

 

# ========================== 核心：负样本提示词模板（与具体标准解耦） ==========================
def get_negative_prompt(text_chunk, source_label, prompt_type):
    prompt_templates = {
        1: f"""任务：为【{source_label}】生成"高后果区识别范围与分级不完整"负样本。
要求：
1. 仅修改高后果区识别范围与分级相关内容，删除或模糊关键信息
2. 保持其他内容不变，仅让识别范围与分级信息不完整
3. 确保修改后的文本仍然通顺，但缺少必要的范围与分级信息
原始文本：
---
{text_chunk}
---
输出：仅返回修改后的文本，无需额外解释。""",
        
        2: f"""任务：为【{source_label}】生成"缺少依据与判定条件引用"负样本。
要求：
1. 仅修改依据与判定条件相关内容，删除或模糊依据表述与引用
2. 保持其他内容不变，仅让依据与判定条件缺失
3. 确保修改后的文本仍然通顺，但缺少依据与判定条件
原始文本：
---
{text_chunk}
---
输出：仅返回修改后的文本，无需额外解释。""",
        
        3: f"""任务：为【{source_label}】生成"敏感目标识别不完整"负样本。
要求：
1. 仅修改敏感目标识别相关内容，删除或模糊人员、环境、社会敏感目标信息
2. 保持其他内容不变，仅让敏感目标识别不完整
3. 确保修改后的文本仍然通顺，但缺少敏感目标识别信息
原始文本：
---
{text_chunk}
---
输出：仅返回修改后的文本，无需额外解释。""",
        
        4: f"""任务：为【{source_label}】生成"高后果区特征描述与附图资料缺失"负样本。
要求：
1. 仅修改特征描述与附图资料相关内容，删除或模糊地理位置、建筑分布、线路图等信息
2. 保持其他内容不变，仅让特征描述与附图资料缺失
3. 确保修改后的文本仍然通顺，但缺少特征描述与附图资料
原始文本：
---
{text_chunk}
---
输出：仅返回修改后的文本，无需额外解释。"""
    }
    return prompt_templates.get(prompt_type, "")

# ========================== 主程序 ==========================
if __name__ == '__main__':
    document_paths = [INPUT_DOCUMENT_PATH]
    
    try:
        file_name_for_prompt = os.path.basename(INPUT_DOCUMENT_PATH)
        print(f"准备处理文档: {file_name_for_prompt}")
    except:
        file_name_for_prompt = "高后果区管控方案"
        print(f"准备处理文档: {INPUT_DOCUMENT_PATH}")
    
    all_generated_data = []
    for doc_path in document_paths:
        print(f"\n{'='*80}\n正在处理文件: {doc_path}\n{'='*80}")
        
        # 读取文档文本
        full_text = read_document(doc_path)
        if full_text.startswith("错误:"):
            print(full_text)
            continue
        
        print(f"成功提取文本，长度: {len(full_text)}字符")
        
        # 将文本切分为语义块
        text_chunks = semantic_chunker(full_text)
        print(f"文本被切分为 {len(text_chunks)} 个语义块进行处理。\n")
        if PROCESS_FIRST_CHUNK_ONLY and text_chunks:
            text_chunks = text_chunks[:1]
            print("已开启快速预览：仅处理第 1 个文本块。\n")
        
        # 遍历每个文本块，生成4个负样本
        for chunk_idx, chunk in enumerate(text_chunks):
            print(f"--- 正在处理第 {chunk_idx+1}/{len(text_chunks)} 个文本块 ---")
            source_label = f"标准遵从度分析 ({file_name_for_prompt} 文本块{chunk_idx+1})"
            
            # 模式匹配与合规评分已关闭，仅进行负样本生成
            
            # 生成4种负样本
            for prompt_type in range(1, 5):
                neg_types = [
                    "高后果区识别范围与分级不完整",
                    "缺少依据与判定条件引用",
                    "敏感目标识别不完整",
                    "高后果区特征描述与附图资料缺失"
                ]
                neg_type = neg_types[prompt_type-1]
                print(f"  → 生成第{prompt_type}/4个负样本（类型：{neg_type}）")
                
                # 获取提示词并调用模型
                prompt = get_negative_prompt(chunk, source_label, prompt_type)
                chat_message = [{"role": "user", "content": prompt}]
                negative_sample = get_answer(chat_message)
                
                # 生成负样本数据
                if negative_sample.strip():
                    all_generated_data.append({
                        "messages": [
                            {
                                "content": f"请检查以下文档的标准遵从度：\n{negative_sample.strip()}",
                                "role": "user"
                            },
                            {
                                "content": f"检测到标准遵从度问题：{neg_type}。正确的标准引用应该是：\n{chunk}",
                                "role": "assistant"
                            }
                        ],
                        "images": [],
                    })
                else:
                    print(f"  → 第{prompt_type}个负样本生成失败，跳过")
                
                time.sleep(1)
    
    # 写入输出文件
    if all_generated_data:
        output_dir = os.path.dirname(OUTPUT_JSON_PATH)
        if not os.path.exists(output_dir):
            try:
                os.makedirs(output_dir)
                print(f"已创建输出目录: {output_dir}")
            except OSError as e:
                print(f"错误: 创建输出目录失败: {e}")
                all_generated_data = []
        
        if all_generated_data:
            try:
                with open(OUTPUT_JSON_PATH, "w", encoding="utf-8") as f:
                    json.dump(all_generated_data, f, ensure_ascii=False, indent=4)
                print(f"\n\n{'='*80}")
                print(f"处理完成！数据保存至：{OUTPUT_JSON_PATH}")
                print(f"共生成 {len(all_generated_data)} 个独立字典（每个字典含1个正样本+1个负样本）")
                print("="*80)
            except Exception as e:
                print(f"错误: 写入JSON失败: {e}")
    else:
        print("\n\n处理结束，无生成数据。请检查PDF文件或API配置。")
